home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
330_03
/
tskprf.asm
< prev
next >
Wrap
Assembly Source File
|
1990-10-10
|
30KB
|
1,659 lines
;
; --- Version 2.2 90-10-12 10:38 ---
;
; CTask - Printf replacement
;
; Public Domain Software written by
; Thomas Wagner
; Ferrari electronic Gmbh
; Beusselstrasse 27
; D-1000 Berlin 21
; Germany
;
; This file is new with Version 2.1.
;
; This module contains substitutes for the standard C printf
; family formatting routines. It uses no helper routines, and
; thus can be called from Assembler programs and is model
; independent. It is smaller and faster (up to 5 times) than
; the standard C printf, and supports all output options except
; floating point and some esoteric flags.
;
; Also supported is output to the second monitor in a dual-
; monitor system.
;
; The routines in this module are reentrant in the sense that nothing
; will crash if routines are re-entered concurrently. No protection
; against a garbled screen is built in, however, so external
; resource request/release calls are still necessary to make
; sure output to the display stays in proper order. The sprintf
; routines need no protection.
;
; No CTask specific stuff is used to allow use of the routines
; even when CTask is not installed.
;
; Note that the tsk_fprintf routine takes a different parameter
; than the standard fprintf. You have to pass an integer file
; handle, not a FILE *.
;
;---------------------------------------------------------------------------
;
; Conversion format:
;
; % [flags] [width] [.precision] [indirection] [size] conversion
;
; Flags supported:
;
; - Left-justify output
;
; the +, blank, and # flags are not supported.
;
; Width and precision are handled like in standard C, i.e.
; the * specification is supported. The only exception is
; that numeric output will not be suppressed for an explicit
; 0 precision.
;
; Size modifiers supported:
;
; N Near pointer
; F Far pointer
; h Short
; l Long
;
; Conversion characters supported:
;
; c single character
; s zero-terminated string
; x unsigned hex word, a-f
; X unsigned hex word, A-F
; d signed decimal int
; u unsigned decimal int
; p hex pointer, a-f
; P hex pointer, A-F
; n store converted length at int pointer
;
; In addition, two indirection operators are supported. Both
; can be repeated, but they should not normally be mixed.
;
; ^ Near indirection (param is DS-based near pointer)
; @ Far indirection (param is far pointer)
;
; Example:
; %d Displays the word parameter
; %^d Displays the word at DS:parameter
; %@d Displays the word at the far address
; given as parameter
;
;---------------------------------------------------------------------------
;
name tskprf
;
include tsk.mac
;
.tsk_model
;
public tsk_regen ; far pointer to regen buffer
public tsk_regen_s ; regen buffer segment
public tsk_regen_o ; current regen buffer offset
public tsk_disport ; display controller I/O port
;
Pubfunc tsk_putc ; put char to screen
Pubfunc tsk_puts ; put string to screen
Pubfunc tsk_rputc ; put char to regen
Pubfunc tsk_rputs ; put string to regen
;
CPubfnc tsk_printf ; print to screen
Pubfunc tsk_vprintf ; print to screen with arg pointer
CPubfnc tsk_fprintf ; print to file handle
Pubfunc tsk_vfprintf ; print to file handle w. argptr
CPubfnc tsk_sprintf ; print to string
Pubfunc tsk_vsprintf ; print to string w. argptr
CPubfnc tsk_rprintf ; print to regen
Pubfunc tsk_vrprintf ; print to regen w. argptr
;
Pubfunc tsk_setpos ; set regen cursor position
Pubfunc tsk_set_regen ; set regen address
Pubfunc tsk_set_dualdis ; init secondary monitor
Pubfunc tsk_set_currdis ; init primary monitor
Pubfunc tsk_set_colour ; init colour monitor
Pubfunc tsk_set_mono ; init mono monitor
Pubfunc tsk_set_attr ; set display attribute
Pubfunc tsk_set_clreol ; CR clears to EOL when set
;
;
; Configuration options:
;
; FILE_BUFSIZE Is the local buffer size for tsk_fprintf and tsk_vfprintf.
; The buffer is allocated on the stack, so it should
; not be chosen too large to avoid stack overflows.
; It must be a power of 2, and less than or equal to 256.
;
FILE_BUFSIZE = 64 - 1
;
;
; DFLT_FAR If set, pointers (%p and %n) and strings (%s) are assumed
; far by default, near pointers must use the N size
; modifiers.
; If clear, the default is near, so the F size modifier
; must be used for far pointers.
;
DFLT_FAR = 1 ; by default, pointers and strings are Far
;
;
; The local variables used in the main formatter.
; Those variables are relative to BP, and are accessed by
; several routines in this module (the local routines do not
; use the standard stack discipline, they should be viewed as
; Pascal-like nested routines within the scope of @disprintf).
;
dislocrec struc
convbuf db 11 dup(?) ; conversion buffer (hex/dec)
prflags db ? ; formatting flags
prhexch db ? ; Hex format offset for upper/lower case
prfcnt db ? ; file output counter
procnt dw ? ; output char counter
prwidth dw ? ; field width
prec dw ? ; precision
arglen dw ? ; argument length in bytes
prproc dw ? ; output routine offset
prargbx dw ? ; output routine BX argument
prargdx dw ? ; output routine DX argument
dislocrec ends
;
; formatting flags
;
F_LONGARG = 01h ; argument is long/far (4 bytes)
F_SHORTARG = 02h ; argument is single byte
F_PADZERO = 04h ; pad with zeros
F_LEFTADJ = 08h ; left adjust output
F_SIGNED = 10h ; signed number
F_WIDTH = 20h ; width is valid
F_PREC = 40h ; precision is valid
F_INDIR = 80h ; indirection was used
;
biosdata segment at 40h
org 4ah
bios_cols dw ?
org 63h
bios_chipad dw ?
org 84h
bios_rows db ?
biosdata ends
;
.tsk_data
;
tsk_regen label dword
tsk_regen_o dw 0
tsk_regen_s dw 0b000h ; default mono screen
;
tsk_disport dw 3b4h ; default mono 6845
tsk_attrib db 07h ; default white on black
;
sc_clreol db 0 ; default is don't clear
;
sc_cols dw 80 * 2
sc_end dw 25 * 80 * 2
;
sc_proc dw offset @nodis
;
.tsk_edata
.tsk_code
;
ctdataseg dw @CTASK_DATA
;
; setcsr - local routine to set the cursor to the current position
; on the regen display.
;
@setcsr proc near
;
push dx
mov dx,tsk_disport
or dx,dx
jz no_cursor
mov al,0eh
out dx,al
jmp $+2
mov ax,tsk_regen_o
shr ax,1
xchg ah,al
inc dx
out dx,al
jmp $+2
dec dx
mov al,0fh
out dx,al
jmp $+2
mov al,ah
inc dx
out dx,al
;
no_cursor:
pop dx
ret
;
@setcsr endp
;
;
; disregen - local routine to write char directly into the display
; regen buffer. The following control characters
; are handled special:
; 08 \b (BS) backspace one position (no erase)
; 09 \t (TAB) tab to next 8th column
; 0D \r (CR) carriage return
; 0A \n (LF) line feed
; Note: the printf routines will not pass
; a single line feed unchanged.
; 0B \v (VT) clear to end of line
; 0C \f (FF) clear to end of screen
;
;
; Entry: AL = char to display
; Uses: AX
;
@disregen proc near
;
push ds
mov ds,cs:ctdataseg ; allow access to local vars
;
; First, check for control characters
;
cmp al,0eh ; 08-0D are special
jae no_special
cmp al,08h
jb no_special
je dis_bs ; 08 = Backspace
cmp al,0ah
jb dis_tab ; 09 = Tab
je dis_lf ; 0A = Linefeed
cmp al,0ch
jb dis_vt ; 0B = Clear to eol
jne dis_cr ; 0D = Carriage return
jmp dis_ff ; 0C = Clear screen
;
; Carriage return
;
dis_cr:
cmp sc_clreol,0
jne dis_vt
discr1:
push dx
cli
mov ax,tsk_regen_o ; current offset
xor dx,dx ; make into doubleword
div sc_cols ; divide by number of columns
sub tsk_regen_o,dx ; subtract remainder
sti
pop dx
jmp disreg_end
;
no_special:
jmp disregen_ok
;
; Backspace
;
dis_bs:
cli
cmp tsk_regen_o,0 ; Handle wraparound
je dis_bs2
sub tsk_regen_o,2
sti
jmp disreg_end
dis_bs2:
mov ax,sc_end ; Wrap to end of screen
sub ax,2
mov tsk_regen_o,ax
sti
jmp disreg_end
;
; Tab
;
dis_tab:
cli
mov ax,tsk_regen_o
add ax,16
and ax,0fff0h ; Tabs every 8 cols
mov tsk_regen_o,ax
sti
jmp disreg_end
;
; Linefeed
;
dis_lf:
cli
mov ax,tsk_regen_o
add a